<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2022/4/12
 * Time: 17:44
 */

namespace app\logic\index\novel;


use app\common\lib\Common;
use app\common\lib\Constant;
use app\common\lib\DouYinOpenApp;
use app\common\lib\Oceanengine;
use app\exception\IndexException;
use app\logic\BaseLogic;
use app\logic\cron\HinovelLogic;
use app\model\manage\SearchManageModel;
use app\model\novel\NovelBusinessModel;
use app\model\novel\NovelChapterModel;
use app\model\oceanengine\OceanengineAcceptedTaskListModel;
use app\model\overseas\HinovelDataModel;
use app\model\overseas\UserHinovelPasswordCodeDataModel;
use app\model\plan\PromotionPlanModel;
use app\model\reward\RewardPlanModel;
use app\model\user\UserModel;
use support\Cache;
use support\Db;

class NovelLogic extends BaseLogic
{
    protected $model;

    protected static $instance;

    public function __construct()
    {
        parent::__construct();
        $this->model = \app\model\novel\NovelSpreadModel::getInstance();
    }

    public static function getInstance()
    {
//        if(is_object(self::$instance)){
//            return self::$instance;
//        }

        return  new self();
    }

    public function getList($param)
    {
        if (!empty($param['keyword'])) {
            $spreadType = 0;
        }else{
            $spreadType = $param['spread_type']??1;
        }

        $fields = [ 'novel_sn','title','main_image','platform','payment_allocate_ratio',
                    'business_id','labels','desc', 'created_at', 'app_id', 'start_time',
                    'data_source_key','total_spread_num','total_heighest_income','total_income','total_like_nums',
                    'commission','first_category','second_category','words_num','spread_type','book_id','lang',
        ];

        $bWhere = ['status'=>1,'isdel'=>0];
        $spreadType>0 && $bWhere['spread_type'] = $spreadType;
        $businessIds = NovelBusinessModel::getInstance()->getWhere($bWhere)->pluck('id')->toArray();
        $novelSns = PromotionPlanModel::getInstance()->getWhere(['status'=>1,'isdel'=>0,['part_nums','>',0]])->pluck('novel_sn')->toArray();
        $where = [
            'isdel'=>0,
            'status'=>1,
            ['business_id','in',$businessIds],
            //['novel_sn','in',$novelSns]
        ];

        $spreadType>0 && $where['spread_type'] = $spreadType;
        if($spreadType==1){
            $where['task_status'] = 2;
            $where[] =  ['novel_sn','in',$novelSns];
        }elseif($spreadType==2){
            $where['under_status'] = 1;
            $where[] =  ['novel_sn','in',$novelSns];
        }elseif($spreadType==3){

        }

        if (!empty($param['business_id'])) {
            $where[] = ['business_id', '=', $param['business_id']];
        }
        if (!empty($param['keyword'])) {
            $where[] = [
                'or'=>[
                    [['title', 'like', "%{$param['keyword']}%"]],
                    [['labels', 'like', "%{$param['keyword']}%"]],
                ]
            ];
            if(Common::checkIngStatus()){
                $where['spread_type'] = 1;
            }else{
                unset($where['spread_type']);
            }
        }

        if(!empty($param['order_field'])){
            $param['order_field']=='payment_allocate_ratio' && ($param['order_type'] = $param['order_type']=='desc'? 'asc':'desc');
            $param['order_field']=='complex' && $param['order_field'] = 'start_time';
            $order = [$param['order_field'], $param['order_type']??'desc'];
        }elseif(!empty($param['rand_order'])){
            $order = 'RAND()';
        }else{
            $order = ['start_time', 'desc'];
        }

        $list =  $this->model->index($where, $fields, $order);

        $businessMap = $this->getListMapById(NovelBusinessModel::getInstance(),$list['data']->toArray(),'business_id','id');
        $user = UserModel::getInstance()->getWhere(['user_sn'=>request()->curUserId])->first(['agent_level','reward_plan_id','talent_commission_rate','direct_commission_rate']);
        $levelRewardsFirst=false;
        if($user && $user['reward_plan_id']>0){
            $levelRewardsFirst = RewardPlanModel::getInstance()->find($user['reward_plan_id']);
        }
        if($levelRewardsFirst==false){
            $levelRewardsFirst = RewardPlanModel::getInstance()->find(1);
        }
        $agentLevel = UserModel::getInstance()->getUserAgentVip(request()->curUserId);
        $userTalentRate = json_decode($levelRewardsFirst['v'.$agentLevel.'_plan_data'],true)['talent_rate'];

        $commissionRateMap = getcommissionRate(request()->curUserId);

        foreach ($list['data'] as $k => $val) {
            $update = [];
            //随机最高收益
            if($val['total_heighest_income']<500){
                $update['virtual_highest_income'] = $val->virtual_highest_income = mt_rand(500,3000);
                $update['total_heighest_income'] = $val->total_heighest_income = round($val->virtual_highest_income+$val->really_heighest_income);
            }
            $val->total_heighest_income = (string) $val->total_heighest_income;
            //随机推广人数
            if($val['total_spread_num']<500){
                $update['virtual_spread_num'] =  $val->virtual_spread_num = mt_rand(500,3000);
                $update['total_spread_num'] =  $val->total_spread_num =  round($val->virtual_spread_num+$val->really_spread_num);
            }
            $val->total_spread_num =  (string) $val->total_spread_num;
            //随机推广收益
            if($val['total_income']<500){
                $update['virtual_income'] = $val->virtual_income = mt_rand(500,3000);
                $update['total_income'] = $val->total_income =  round($val->virtual_income+$val->really_income);
            }
            $val->total_income = (string) $val->total_income;
            //随机点赞数
            if($val['total_like_nums']<5000){
                $update['total_like_nums'] = $val->total_like_nums = mt_rand(5000,30000);
            }
            $val->total_like_nums =  (string) $val->total_like_nums;
            $update && $this->model->getWhere(['novel_sn'=>$val['novel_sn']])->update($update);

            if(strtotime($val['created_at'])>=strtotime(date('Y-m-d'))){
                $val['is_recom'] = 1;
            }else{
                $val['is_recom'] = 0;
            }

            $val['first_category'] = (string)($val['first_category']?:(explode(',',$val['labels'])[0]??''));
            $val['second_category'] = (string)($val['second_category']?:(explode(',',$val['labels'])[1]??''));
            $val['commission'] = (string)$val['commission'];
            $val['spread_type'] = (string)$val['spread_type'];
            $val['start_time'] = date('Y-m-d',strtotime($val['start_time']));
            $val['business_name'] = $businessMap[$val['business_id']]['name']??'';
            $val['business_logo'] = $businessMap[$val['business_id']]['logo']??'';

            //达人奖励比例
            if(request()->curUserId){
                //星图佣金
                if($val['data_source_key']==OceanengineAcceptedTaskListModel::getInstance()->getTable()){
                    $val['platform_allocate_ratio'] = (string) ($commissionRateMap['星图佣金']['talent_commission_rate']??Constant::OCEANENGINE_TALENT_COMMISSION_RATE);
                    $val['platform_allocate_ratio']<Constant::OCEANENGINE_TALENT_COMMISSION_RATE && $val['platform_allocate_ratio'] = (string) Constant::OCEANENGINE_TALENT_COMMISSION_RATE;
                    $val['payment_allocate_ratio'] = (string) Constant::OCEANENGINE_TALENT_COMMISSION_RATE;
                }elseif($val['data_source_key']==HinovelDataModel::getInstance()->getTable()){
                    $val['platform_allocate_ratio'] = (string) ($commissionRateMap['Hinovel佣金']['talent_commission_rate']??Constant::HINOVEL_TALENT_COMMISSION_RATE);
                    $val['platform_allocate_ratio']<Constant::HINOVEL_TALENT_COMMISSION_RATE && $val['platform_allocate_ratio'] = (string) Constant::HINOVEL_TALENT_COMMISSION_RATE;
                    $val['payment_allocate_ratio'] = (string) Constant::HINOVEL_TALENT_COMMISSION_RATE;
                }else{
                    $paymentAllocateRatio = round($val['payment_allocate_ratio']/105,2);
                    $paymentAllocateRatios = explode('.',(string)$paymentAllocateRatio);
                    $paymentAllocateRatios[1] = !empty($paymentAllocateRatios[1]) ? '.'.substr($paymentAllocateRatios[1],0,1) : '';
                    $val['payment_allocate_ratio'] = (string)($paymentAllocateRatios[0].$paymentAllocateRatios[1]);

                    //$val['platform_allocate_ratio'] = (float) ($userTalentRate-$val['payment_allocate_ratio']);
                    if(((float)$val['payment_allocate_ratio'])>((float)$userTalentRate)){
                        $val['platform_allocate_ratio'] = (string)$val['payment_allocate_ratio'];
                    }else{
                        $val['platform_allocate_ratio'] = (string)$userTalentRate;
                    }
                }

            }else{
                if($val['data_source_key']==OceanengineAcceptedTaskListModel::getInstance()->getTable()){
                    $val['payment_allocate_ratio'] = (string) Constant::OCEANENGINE_TALENT_COMMISSION_RATE;
                    $val['platform_allocate_ratio'] = (string) Constant::OCEANENGINE_TALENT_COMMISSION_RATE;
                }elseif($val['data_source_key']==HinovelDataModel::getInstance()->getTable()){
                    $val['payment_allocate_ratio'] = (string) Constant::HINOVEL_TALENT_COMMISSION_RATE;
                    $val['platform_allocate_ratio'] = (string) Constant::HINOVEL_TALENT_COMMISSION_RATE;
                }else{
                    $paymentAllocateRatio = round($val['payment_allocate_ratio']/105,2);
                    $paymentAllocateRatios = explode('.',(string)$paymentAllocateRatio);
                    $paymentAllocateRatios[1] = !empty($paymentAllocateRatios[1]) ? '.'.substr($paymentAllocateRatios[1],0,1) : '';
                    $val['payment_allocate_ratio'] = (string)($paymentAllocateRatios[0].$paymentAllocateRatios[1]);
                    $val['platform_allocate_ratio'] = (string) config('param.user_talent_rate','52');
                }
            }
        }
        $list['data'] = $list['data']->toArray();

        return $list;
    }

    public function getBusinessList($param)
    {
        $fields = [ 'id','name','logo','sort','platform',];

        $where = [
            'isdel'=>0,
            'status'=>1,
            'spread_type'=>$param['spread_type']??1,
        ];
        $order = ['sort', 'desc'];

        $list =  NovelBusinessModel::getInstance()->index($where, $fields, $order);

        return $list;
    }

    public function getCooperateLink($param)
    {
        $field = ['novel_sn','title','task_id','task_status','status','platform','app_id','data_source_id',
                  'data_source_key','business_id','lang'];

        $detail = $this->model->getWhere(['novel_sn'=>$param['novel_sn']])->first($field);
        if($detail==false){
            throw new IndexException(4020,'数据不存在');
        }
        //appurl
        $detail['app_url'] = '';
        if($detail['platform']==1){
            if($detail['task_status']!=2){
                throw new IndexException(4020,'当前小说已下架');
            }
            if(!empty($detail['task_id']) && $detail['task_status']==2){
                //星图任务链接
                if($detail['data_source_key']==OceanengineAcceptedTaskListModel::getInstance()->getTable()){
                    if(request()->curUserInfo['mobile']==false){
                        throw new IndexException(4020,'手机号登录才可直接推广');
                    }
                    $result = Oceanengine::getInstance()->getTaskLink($detail['task_id'],request()->curUserId);
                    if(!empty($result['task_url'])){
                        $detail['app_url'] = 'snssdk1128://webview?url='.urlencode($result['task_url']);
                    }
                }else{
                    $agentid = config('param.open_douyin_app')['agent_id'];
                    $result = DouYinOpenApp::getInstance()->getCooperateLink($agentid,null,$detail['task_id'],request()->curUserId);
                    if(!empty($result['data']['app_link'])){
                        $detail['app_url'] = 'snssdk1128://microapp?app_id=ttf31985a46c214faf&start_page='.urlencode($result['data']['app_link']);
                    }
                }

            }
        }elseif($detail['business_id']==1000){
            $where = ['novel_sn'=>$detail['novel_sn'],'user_sn'=>request()->curUserId];
            $passCode = UserHinovelPasswordCodeDataModel::getInstance()->getWhere($where)->value('password_code');
            if($passCode){
                $detail['app_url'] = HinovelLogic::getInstance()->getCooperateLink($passCode,$detail['lang']);
            }
        }

        return $detail;
    }

    public function getDetail($param)
    {
        $field = ['novel_sn','title','main_image','platform','business_id','labels','desc',
                  'total_income','created_at','episode_num','is_end','start_time','app_id','data_source_key'
                  ,'total_heighest_income','total_spread_num','total_like_nums','task_id','task_status','payment_allocate_ratio'
                  ,Db::raw('\'novel\' promotion_type'),
                  'commission','first_category','second_category','words_num','spread_type','book_id','under_status','lang',
        ];

        $detail = $this->model->getWhere(['novel_sn'=>$param['novel_sn']])->first($field);
        if($detail==false){
            throw new IndexException(4020,'当前小说不存在');
        }

        $businessName = NovelBusinessModel::getInstance()->getWhere(['id'=>$detail['business_id']])->first(['name','logo']);
        $detail['business_name'] = $businessName['name']??'';
        $detail['business_logo'] = $businessName['logo']??'';

        $user = UserModel::getInstance()->getWhere(['user_sn'=>request()->curUserId])->first(['agent_level','reward_plan_id','talent_commission_rate','direct_commission_rate']);

        //星图佣金
        if($detail['data_source_key']==OceanengineAcceptedTaskListModel::getInstance()->getTable()){
            $commissionRateMap = getcommissionRate(request()->curUserId);
            $detail['total_ratio'] = (string) ($commissionRateMap['星图佣金']['talent_commission_rate']??Constant::OCEANENGINE_TALENT_COMMISSION_RATE);
            $detail['total_ratio']<Constant::OCEANENGINE_TALENT_COMMISSION_RATE && $detail['total_ratio'] = (string) Constant::OCEANENGINE_TALENT_COMMISSION_RATE;
            $detail['payment_allocate_ratio'] = (string) Constant::OCEANENGINE_TALENT_COMMISSION_RATE;
            $detail['platform_allocate_ratio'] = (string) round(((int)$detail['total_ratio']) - ((int)$detail['payment_allocate_ratio']));
            $detail['platform_allocate_ratio']<0 && $detail['platform_allocate_ratio'] = '0';
        }elseif($detail['data_source_key']==HinovelDataModel::getInstance()->getTable()){
            $commissionRateMap = getcommissionRate(request()->curUserId);
            $detail['total_ratio'] = (string) ($commissionRateMap['Hinovel佣金']['talent_commission_rate']??Constant::HINOVEL_TALENT_COMMISSION_RATE);
            $detail['total_ratio']<Constant::HINOVEL_TALENT_COMMISSION_RATE && $detail['total_ratio'] = (string) Constant::HINOVEL_TALENT_COMMISSION_RATE;
            $detail['payment_allocate_ratio'] = (string) $detail['total_ratio'];
            $detail['platform_allocate_ratio'] = (string) round(((int)$detail['total_ratio']) - ((int)$detail['payment_allocate_ratio']));
            $detail['platform_allocate_ratio']<0 && $detail['platform_allocate_ratio'] = '0';
        }else{
            //达人奖励比例
            $levelRewardsFirst=false;
            if($user['reward_plan_id']>0){
                $levelRewardsFirst = RewardPlanModel::getInstance()->find($user['reward_plan_id']);
            }
            if($levelRewardsFirst==false){
                $levelRewardsFirst = RewardPlanModel::getInstance()->find(1);
            }

            $agentLevel = UserModel::getInstance()->getUserAgentVip(request()->curUserId);
            $userTalentRate = json_decode($levelRewardsFirst['v'.$agentLevel.'_plan_data'],true)['talent_rate'];

            $paymentAllocateRatio = round($detail['payment_allocate_ratio']/105,2);
            $paymentAllocateRatios = explode('.',(string)$paymentAllocateRatio);
            $paymentAllocateRatios[1] = $paymentAllocateRatios[1]??'0';
            $detail['payment_allocate_ratio'] = (string)($paymentAllocateRatios[0].'.'.substr($paymentAllocateRatios[1],0,1));
            $detail['platform_allocate_ratio'] = (string) ($userTalentRate-$detail['payment_allocate_ratio']);
            $detail['platform_allocate_ratio'] = (string) ($detail['platform_allocate_ratio'] >0 ? $detail['platform_allocate_ratio'] : 0.0);
            $detail['total_ratio'] = (string) round($detail['platform_allocate_ratio']+$detail['payment_allocate_ratio'],1);
        }

        $detail['novel_link'] = '';
        $detail['password_code'] = '';
        $detail['promotion_words'] = [];
        if($detail['business_id']==777){
            $detail['novel_link'] = 'https://spread.wtzw.com/front/spread/bdss/bdss_'.$detail['book_id'].'.html';
        }elseif($detail['business_id']==1000){
            //获取口令 游客情况下口令是空的
            $passCode = '';
            if(!empty(request()->curUserInfo['mobile'])){
                $passCode = (string) UserHinovelPasswordCodeDataModel::getInstance()->getWhere(['user_sn'=>request()->curUserId,'novel_sn'=>$detail['novel_sn']])->value('password_code');
            }

            //推广文案
            $promotionWords = array_filter(explode('|@@|',config('param.hinovel_promotion_words','')));
            foreach($promotionWords as &$v){
                $v = $passCode ? str_replace('@code',$passCode,$v) : $v;
            }
            $detail['promotion_words'] = $promotionWords;
            $detail['password_code'] = $passCode;
        }

        $detail['keyword_precautions'] = config('param.novel_spread_keyword_precautions','');

        $detail['commission'] = (string)$detail['commission'];
        $detail['spread_type'] = (string)$detail['spread_type'];
        $detail['start_time'] = date('Y-m-d',strtotime($detail['start_time']));
        $detail['created_at'] = date('Y-m-d',strtotime($detail['created_at']));

        if($detail['spread_type']==2){
            $detail['task_status'] = $detail['under_status']==1 ? 2 : 0;
        }elseif($detail['spread_type']==3){
            $detail['task_status'] = 2;
        }

        //章节列表
        $chapters = NovelChapterModel::getInstance()->getWhere(['novel_sn'=>$detail['novel_sn'],'status'=>1,'isdel'=>0])->get(['id','number','original_content']);
        $chapterList = [];
        foreach ($chapters as $chapter){
            $chapterList[] = [
                'chapter_id'=>$chapter['id'],
                'name'=>'第'.$chapter['number'].'章',
                'content'=>$chapter['original_content'],
            ];
        }
        $detail['chapters'] = $chapterList;

        return $detail;
    }

    public function getHotsSearchWord()
    {
        $data = Cache::get('skit_hots_word_list');
        if($data){
            return $data;
        }

        $where = [
            'isdel'=>0,
            'status'=>1,
        ];

        $field = ['id','name','manage_data'];
        $homeSkits =  SearchManageModel::getInstance()->getWhere($where)->orderBy('sort', 'asc')->limit(2)->get($field)->toArray();

        $todayHotsWords = [];
        $weekHotsWords = [];
        foreach($homeSkits as $k=>$homeSkit){
            $novelData = $homeSkit['manage_data'] ? json_decode($homeSkit['manage_data'],true):[];
            $ids = [];
            foreach($novelData as $val){
                $ids[] = $val['id'];
            }
            $where = ['isdel'=>0, 'status'=>1, 'task_status'=>2,['id','in',$ids]];
            $novelIds = $this->model->getWhere($where)->pluck('id')->toArray();

            $names = [];
            foreach ($novelData as $key=>$val){
                if(in_array($val['id'],$novelIds)){
                    $names[] = $val['name'];
                }
                if(count($names)>=10){
                    break;
                }
            }

            $k==0 &&  $todayHotsWords = $names;
            $k==1 &&  $weekHotsWords = $names;
        }

        //如果是空的，拿列表随机
        if(empty($todayHotsWords)){
            $novelList1 = $this->getList(['spread_type'=>1,'rand_order'=>1]);
            $novelList2 = $this->getList(['spread_type'=>2,'rand_order'=>1]);
            $novelData = [];
            if(!empty($novelList1['data'])){
                $novelData = array_merge($novelData,$novelList1['data']);
            }
            if(!empty($novelList2['data'])){
                $novelData = array_merge($novelData,$novelList2['data']);
            }
            shuffle($novelData);

            $names = [];
            foreach ($novelData as $key=>$val){
                $names[] = $val['title'];
                if(count($names)>=10){
                    break;
                }
            }

            $todayHotsWords = $names;
        }

        if(empty($weekHotsWords)){
            $novelList1 = $this->getList(['spread_type'=>1,'rand_order'=>1]);
            $novelList2 = $this->getList(['spread_type'=>2,'rand_order'=>1]);
            $novelData = [];
            if(!empty($novelList1['data'])){
                $novelData = array_merge($novelData,$novelList1['data']);
            }
            if(!empty($novelList2['data'])){
                $novelData = array_merge($novelData,$novelList2['data']);
            }
            shuffle($novelData);

            $names = [];
            foreach ($novelData as $key=>$val){
                $names[] = $val['title'];
                if(count($names)>=10){
                    break;
                }
            }

            $weekHotsWords = $names;
        }

        $data = ['today_hots_word'=>$todayHotsWords,'week_hots_word'=>$weekHotsWords];
        $todayHotsWords && $weekHotsWords && Cache::set('skit_hots_word_list',$data,300);

        return $data;
    }

    public function getPlanIdAndPoints($param)
    {
        $detail = $this->model->getWhere(['novel_sn'=>$param['novel_sn']])->first();
        if($detail==false){
            throw new IndexException(4020,'当前小说不存在');
        }

        //随机获取当前小说的一个方案
        $where = ['isdel' => 0, 'status' => 1, 'novel_sn' => $param['novel_sn']];
        $plan = PromotionPlanModel::getInstance()->getWhere($where)->orderBy(Db::Raw('RAND()'))->first();
        if ($plan == false) {
            throw new IndexException(4020, '当前推文不可用');
        }
        if ($plan['part_nums'] == false) {
            throw new IndexException(4020, '当前推文不可用');
        }

        $count = $plan['part_nums'];
        $totoalPonint = round($plan['part_nums']*config('param.image_consume_point',10));

        return ['id'=>$plan['id'],'count'=>$count,'total_point'=>$totoalPonint];
    }

    public function createHinovelPassword($param)
    {
        $detail = $this->model->getWhere(['novel_sn'=>$param['novel_sn']])->first();
        if($detail==false){
            throw new IndexException(4020,'当前小说不存在');
        }
        if($detail['business_id']!=1000){
            throw new IndexException(4020,'海外推文才可创建口令');
        }

        if(empty(request()->curUserInfo['mobile'])){
            throw new IndexException(4020,'手机号登录才可创建口令');
        }

        $passCode = (string) UserHinovelPasswordCodeDataModel::getInstance()->getWhere(['user_sn'=>request()->curUserId,'novel_sn'=>$detail['novel_sn']])->value('password_code');
        //if($passCode==false && strtolower(config('app.app_env'))=='prod'){
        if($passCode==false){
            //正式环境才可真的调用创建口令
            try{
                $passCode = HinovelLogic::getInstance()->getPasswordCode(request()->curUserId,$detail['book_id'],$detail['lang']);
                $insert = [
                    'novel_sn'=>$detail['novel_sn'],
                    'user_sn'=>request()->curUserId,
                    'title'=>$detail['title'],
                    'password_code'=>$passCode,
                ];
                UserHinovelPasswordCodeDataModel::getInstance()->insert($insert);
            }catch (\Throwable $e){}
        }elseif($passCode==false && strtolower(config('app.app_env'))!='prod'){
            $passCode = Common::randString(7,1);
            $insert = [
                'novel_sn'=>$detail['novel_sn'],
                'user_sn'=>request()->curUserId,
                'title'=>$detail['title'],
                'password_code'=>$passCode,
            ];
            UserHinovelPasswordCodeDataModel::getInstance()->insert($insert);
        }

        if($passCode==false){
            throw new IndexException(4020,'创建口令失败,稍后再试');
        }
        return ['password_code'=>$passCode];
    }
}